package joodle.ui;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.util.Set;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import joodle.domain.Canvas;
import joodle.domain.Shape;
import joodle.domain.Shape.Attribute;
import joodle.si.ResourceManager;
import joodle.tools.SelectionObserver;
/**
 * This class is a representation of the attributes panel
 *
 */
@SuppressWarnings("serial")
public class AttributesPanel extends JPanel implements SelectionObserver {
	
	public AttributesPanel() {
		Canvas.instance().addSelectionObserver(this);
		
		setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
		setMaximumSize(new Dimension(0, 80));
		setBorder(BorderFactory.createTitledBorder(ResourceManager.message("Attributes")));
	}
	/**
	 * @see SelectionObserver#selectionChanged(Shape)
	 */
	@Override
	public void selectionChanged(final Shape s) {
		removeAll();

		if(s.isSelected()) {
			JPanel colorPanel = null;
			
			Set<Shape.Attribute> as = s.getAttributeNames();
			for(final Shape.Attribute a : as) {
				switch(a) {
				case COLOR: {
					colorPanel = new JPanel();
					colorPanel.setBorder(BorderFactory.createTitledBorder(ResourceManager.message("Color")));
					add(colorPanel);
					final Color c = (Color) s.getAttributeValue(a);
					final JButton b = new JButton(makeIcon(c));
					colorPanel.add(b);
					b.addActionListener(new ActionListener() {
	
						@Override
						public void actionPerformed(ActionEvent arg0) {
							Color nc = JColorChooser.showDialog( AttributesPanel.this,
									ResourceManager.message("ChooseAColor"), c);
							if(nc != null) {
								s.setAttributeValue(a, nc);
								b.setIcon(makeIcon(nc));
								CanvasComponent.instance().repaint();
							}
						}
					});
					break;
				}
				case FILL_COLOR: {
					if(colorPanel == null) {
						colorPanel = new JPanel();
						colorPanel.setBorder(BorderFactory.createTitledBorder(ResourceManager.message("Color")));
						add(colorPanel);
					}
					final Color c = (Color) s.getAttributeValue(a);
					Icon icon = (c == null) ? ResourceManager.makeIcon("none") : makeIcon(c);
					final JButton b = new JButton(icon);
					colorPanel.add(b);
					b.addActionListener(new ActionListener() {
						
						@Override
						public void actionPerformed(ActionEvent arg0) {
							Color nc = JColorChooser.showDialog( AttributesPanel.this,
									ResourceManager.message("ChooseAColor"), c);
							if(nc != null) {
								s.setAttributeValue(a, nc);
								b.setIcon(makeIcon(nc));
								CanvasComponent.instance().repaint();
							}
						}
					});
					break;
				}
				case FONT:
					final Font f = (Font) s.getAttributeValue(a);
					final JButton b = new JButton(f.getName());

					JPanel fontPanel = new JPanel();
					fontPanel.setBorder(BorderFactory.createTitledBorder(ResourceManager.message("Font")));
					add(fontPanel);
					
					b.setFont(f.deriveFont(12.0f));
					b.addActionListener(new ActionListener() {
	
						@Override
						public void actionPerformed(ActionEvent ae) {
							FontChooser2 fc = new FontChooser2(null);
							fc.setVisible(true);
							Font nf = fc.getSelectedFont();
							if(fc.getSelectedFont() != null) {
								s.setAttributeValue(a, nf);
								b.setFont(nf.deriveFont(12.0f));
								b.setText(nf.getFontName());
								CanvasComponent.instance().repaint();
							}
						}
					});
					fontPanel.add(b);
					break;
				
				case LINE_STROKE:
					JPanel linePanel = new JPanel();
					linePanel.setBorder(BorderFactory.createTitledBorder(ResourceManager.message("Line")));
					add(linePanel);
					
					BasicStroke st = (BasicStroke) s.getAttributeValue(Attribute.LINE_STROKE);
					//changeStrokesWidth(st.getLineWidth());
					final JComboBox cb = new JComboBox(LINE_ICONS);
					final JSpinner sp = new JSpinner();

					//cb.setSelectedIndex(0);
					cb.addActionListener(new ActionListener() {

						@Override
						public void actionPerformed(ActionEvent ae) {
							s.setAttributeValue(Attribute.LINE_STROKE, makeStroke((Integer) sp.getValue(),
									cb.getSelectedIndex()));
							CanvasComponent.instance().repaint();
						}
						
					});
					linePanel.add(cb);
					
					sp.setModel(new SpinnerNumberModel((int) st.getLineWidth(), 1, 40, 1));
					sp.addChangeListener(new ChangeListener() {

						@Override
						public void stateChanged(ChangeEvent ce) {
							s.setAttributeValue(Attribute.LINE_STROKE, makeStroke((Integer) sp.getValue(),
									cb.getSelectedIndex()));
							CanvasComponent.instance().repaint();
						}
						
					});
					
					linePanel.add(sp);
					break;
				
				case TEXT:
					JPanel textPanel = new JPanel();
					textPanel.setBorder(BorderFactory.createTitledBorder(ResourceManager.message("Text")));
					String text = (String) s.getAttributeValue(Attribute.TEXT);
					final JTextArea ta = new JTextArea(text);
					ta.setColumns(10);
					ta.setRows(3);
					ta.setLineWrap(true);
					textPanel.add(ta);
					ta.getDocument().addDocumentListener(new DocumentListener() {

						@Override
						public void changedUpdate(DocumentEvent e) {
						}

						@Override
						public void insertUpdate(DocumentEvent e) { updateText(); }

						@Override
						public void removeUpdate(DocumentEvent e) { updateText(); }
						
						void updateText() {
							String nt = ta.getText();
							s.setAttributeValue(Attribute.TEXT, nt);
							CanvasComponent.instance().repaint();
						}
						
					});
					add(textPanel);
				}
				//add(Box.createHorizontalGlue());
			}
		}
		revalidate();
		repaint();

	}

	private static float[][] LINE_STYLES = new float[][] {
		new float[] { 9.0f },
		new float[] { 5.0f }
	};
	
	private static Icon[] LINE_ICONS = new Icon[] {
		makeLineStyleIcon(1.0f, 0),
		makeLineStyleIcon(1.0f, 1),
		makeLineStyleIcon(1.0f, 2),
	};
	
	/*
	 * style 0 = solid, 1 = dashed, 2 = dotted
	 */
	/**
	 * Creates stroke for the line of the shapes on the status bar
	 * @param width width of the line
	 * @param style the number of the style
	 */
	private static BasicStroke makeStroke(float width, int style) {
		return style > 0 ? new BasicStroke(width, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND,
				1.0f, LINE_STYLES[style - 1], 0.0f) : new BasicStroke(width);
	}
	/**
	 * Creates an icon for LineStyle on the status bar
	 * @param width width of the icon
	 * @param style the number of the style
	 * @return
	 */
	private static Icon makeLineStyleIcon(float width, int style) {
		BufferedImage image = new BufferedImage(70, 20, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g2 = image.createGraphics();
		g2.setColor(Color.black);
		g2.setStroke(makeStroke(width, style));
		g2.drawLine(5, 10, 65, 10);
		g2.dispose();
		return new ImageIcon(image);
	}
	/**
	 * Creates an icon representing the colors on the status bar 
	 * @param c color of the icon
	 * @return an icon object represents the icon created
	 */
	private static Icon makeIcon(Color c) {
		BufferedImage i = new BufferedImage(48, 48,  BufferedImage.TYPE_INT_ARGB);
		
		Graphics g = i.createGraphics();
		g.setColor(c);
		g.fillRect(2, 2, 44, 44);
		g.dispose();
		
		return new ImageIcon(i);
	}
}
